﻿#region using statements

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using NGen;
using NGen.Managers.GUI;
using NGen.Managers.GameObject;
using NGen.Managers.GameState;
using NGen.Managers.Input;
using NGen.Systems.StringAlarms;

using Nuclex.Input;

using Psych.GUILayouts;
using Psych.Misc;
using Psych.Objects.Character;
using Psych.Objects.Enemies;
using NGen.Managers.Collision;

#endregion
namespace Psych.States
{
    /// <summary>
    /// 	State of the game whenever the play screen is displayed
    /// </summary>
    public class GameStatePlay : GameState, IMouseListener, IKeyboardListener, IAlarmListener
    {
        #region local fields

        /// <summary>
        /// 	alarm system used for timed events
        /// </summary>
        private readonly AlarmSystem m_alarms = new AlarmSystem();

        /// <summary>
        /// 	the gui buttons
        /// </summary>
        private readonly GUIElementPlayStateLayout m_gui = new GUIElementPlayStateLayout();
        private readonly GUIElementHUD m_hud = new GUIElementHUD();

        /// <summary>
        /// 	a saved reference to the alarm used to delay levels
        /// </summary>
        private AlarmObject m_levelAlarm;
        private GameLevel m_level1;
        private GameLevel m_level2;
        private GameLevel m_level3;
        private GameLevel m_level4;
        private GameLevel m_level5;
        private GameLevel currentlevel;
        uint idlevel;
        private GameObjectPlayer m_player;
        private GameObjectSlender m_slender;
        private GameObjectStraightJacket m_sj;
        private bool m_shiftHeld;
        private int totalmove;
        private GameObjectPunch m_punch;
        #endregion

        #region local methods

        /// <summary>
        /// 	Called whenever a gui button gets pressed. This is setup in the
        /// 	initialize function
        /// </summary>
        /// <param name = "guiEvent">a string to represent the event</param>
        private void _GUIEvent(string guiEvent)
        {
            switch (guiEvent)
            {
                case "startPressed":

                    break;
            }
        }

        #region GameState implementation

        /// <summary>
        /// 	_Initialize this game state
        /// </summary>
        protected override void _Initialize()
        {
            //load the game world
           //m_level2 = new GameLevel(2);
          /* m_level3 = new GameLevel(3);
           m_level4 = new GameLevel(4);
           m_level5 = new GameLevel(5);*/

          // currentlevel = m_level1;
           // GameEngine.GetService<IManagerGameObjects>().AddObject(m_level);

            //load the gui
            GameEngine.GetService<IManagerGUI>().AddElement(m_gui);
            GameEngine.GetService<IManagerGUI>().AddElement(m_hud);

            var stats = new GameStats
            {
                Health =100,
                Mental = 100,
                Insanity = 0,
                Level = 1,
                moving = 0
            };
            var stuff = new interact
            {
                ScreenSize = 800,
                LevelSize = 0
            };

            if (GameEngine.GetService<GameStats>() != null)
            {
                GameEngine.GameServices.RemoveService(typeof(GameStats));
            }
            GameEngine.GameServices.AddService(typeof(GameStats),stats); //game stats, info


            m_level1 = new GameLevel(GameEngine.GetService<GameStats>().Level); //load up first level

            currentlevel = m_level1;
            GameEngine.GetService<IManagerGameObjects>().AddObject(currentlevel);

            m_gui.GuiEvent += _GUIEvent; //listen for gui button presses

            // loads enemies
            m_slender = new GameObjectSlender();
            GameEngine.GetService<IManagerGameObjects>().AddObject(m_slender);
            GameEngine.GetService<IManagerCollision2D>().RegisterCollidable(m_slender.Id, false);
            m_sj = new GameObjectStraightJacket();
            GameEngine.GetService<IManagerGameObjects>().AddObject(m_sj);
            GameEngine.GetService<IManagerCollision2D>().RegisterCollidable(m_sj.Id, false);

            //load the player
            m_player = new GameObjectPlayer();
            GameEngine.GetService<IManagerGameObjects>().AddObject(m_player);
            GameEngine.GetService<IManagerCollision2D>().RegisterCollidable(m_player.Id,false);
            
        }

        /// <summary>
        /// 	Perform all necessary actions to cleanup after this state exits
        /// </summary>
        protected override void _Cleanup()
        {
            GameEngine.GetService<IManagerGUI>().RemoveElement(m_gui);
            GameEngine.GetService<IManagerGUI>().RemoveElement(m_hud);
            GameEngine.GetService<IManagerInput>().RemoveMouseListener(this);
            GameEngine.GetService<IManagerInput>().RemoveKeyboardListener(this);
            GameEngine.GetService<IManagerGameObjects>().DestroyAllGameObjects();
        }

        /// <summary>
        /// 	Called whenever this state is no longer the active state
        /// </summary>
        protected override void _OnFocusLost()
        {
            //this state shouldn't receive input while its not active
            GameEngine.GetService<IManagerInput>().RemoveKeyboardListener(this);
            GameEngine.GetService<IManagerInput>().RemoveMouseListener(this);
            GameEngine.GetService<IManagerGameObjects>().SkipUpdate = true;
        }

        /// <summary>
        /// 	Called whenever this state becomes the active state
        /// </summary>
        protected override void _OnFocusGained()
        {
            //this state should receive input again
            GameEngine.GetService<IManagerInput>().AddKeyboardListener(this);
            GameEngine.GetService<IManagerInput>().AddMouseListener(this);
            GameEngine.GetService<IManagerGameObjects>().SkipUpdate = false;
        }

        /// <summary>
        /// 	Update the game for this frame
        /// </summary>
        /// <param name = "p_gameTime">snapshot of timing values</param>
        protected override void _Update(GameTime p_gameTime)
        {
           m_alarms.Update(p_gameTime);
           currentlevel.Update();
        }

        /// <summary>
        /// 	_Draw the game for this frame
        /// </summary>
        /// <param name = "p_gameTime">snapshot of timing values</param>
        protected override void _Draw(GameTime p_gameTime)
        {
            //clear the backbuffer
            GameEngine.GraphicsDeviceManager.GraphicsDevice.Clear(Color.Transparent);

            //initialize the backbuffer
            GameEngine.SpriteBatch.Begin();

            currentlevel.Draw();

            //render to backbuffer
            GameEngine.SpriteBatch.End();
        }

        #endregion

        #region IMouseListener implementation

        /// <summary>
        /// 	Called whenever the mouse moves
        /// </summary>
        /// <param name = "x">x value of mouse position</param>
        /// <param name = "y">y value of mouse position</param>
        public void MouseMoved(float x, float y)
        {
            //if mouse is outside map bounds, move tower offscreen
            if (x >= 588 ||
               x < 12)
            {
                x = -1000;
            }
            if (y >= 588 ||
               y < 12)
            {
                y = -1000;
            }

        }

        /// <summary>
        /// 	Called whenever a mouse button is pressed
        /// </summary>
        /// <param name = "button">the button pressed</param>
        public void MousePressed(MouseButtons button) { }

        /// <summary>
        /// 	Called whenever a mouse button is released
        /// </summary>
        /// <param name = "button">the button released</param>
        public void MouseReleased(MouseButtons button) { }

        /// <summary>
        /// 	Called whenever the mouse wheel is scrolled
        /// </summary>
        /// <param name = "ticks">the number of ticks scrolled</param>
        public void MouseWheelScroll(float ticks) { }

        #endregion

        #region IKeyboardListener implementation

        /// <summary>
        /// 	Called whenever a keyboard button is pressed
        /// </summary>
        /// <param name = "key">the key pressed</param>
        public void KeyPressed(Keys p_key)
        {
            int move = 0;
            
            if (p_key == Keys.Left)
            {
                if (m_player.m_position.X > 0)
                {
                    move = 10;
                    totalmove = totalmove + move;
                    m_player.m_position.X -= 10;
                }
            }

            if (p_key == Keys.Right)
            {
                if(((currentlevel == m_level1) && (m_player.m_position.X <= 2267)) ||
                    ((currentlevel == m_level2) && (m_player.m_position.X <= 3905)))
                {
                    move = -10;
                    totalmove = totalmove + move;
                    m_player.m_position.X += 10;
                }
            }
            if (p_key == Keys.D)
            {
                GameEngine.GetService<IManagerGameObjects>().DestroyGameObjectById(currentlevel.Id);
                GameEngine.GetService<IManagerGameObjects>().AddObject(m_level1);
                move = GameEngine.GetService<GameStats>().moving;
            }
            if (p_key == Keys.Up)
            {
                //if(GameEngine.GetService<GameStats>().Level)
                GameEngine.GetService<IManagerGameObjects>().DestroyGameObjectById(currentlevel.Id);
                GameEngine.GetService<GameStats>().Level = 2;
                m_level2 = new GameLevel(GameEngine.GetService<GameStats>().Level);
                currentlevel = m_level2;
                GameEngine.GetService<GameStats>().moving = totalmove;
                
                GameEngine.GetService<IManagerGameObjects>().AddObject(currentlevel);
                move = -totalmove;
                m_player.m_position.X = 275;
                totalmove = 0;

            }
            GameEngine.GetService<IManagerGameObjects>().TransformMatrix =
                GameEngine.GetService<IManagerGameObjects>().TransformMatrix *
                Matrix.CreateTranslation(new Vector3(move, 0, 0));

            if (p_key == Keys.Escape)
            {
             var state = new GameStatePause();
             //this is just to have the pause state call the play state draw
             state.ThrowDrawEvent += _Draw;
             GameEngine.GetService<IManagerGameState>().PushState(state);
            }

            //Punch
            if (p_key == Keys.Space)
            {
                m_punch = new GameObjectPunch();
                m_punch.m_position = m_player.m_position + new Vector2(100f,0);
                GameEngine.GetService<IManagerGameObjects>().AddObject(m_punch);
                GameEngine.GetService<IManagerCollision2D>().RegisterCollidable(m_punch.Id, false);

            }

            if (p_key == Keys.F12)
            {
                GameEngine.GetService<GameStats>().Health = 100;
            }
            #region Test Keys
            
            //Test keys for HUD
            if (p_key == Keys.A)
            {
                GameEngine.GetService<GameStats>().Health += -10;
            }
            if (p_key == Keys.S)
            {
                GameEngine.GetService<GameStats>().Health += +10;
            }
            if (p_key == Keys.Z)
            {
                GameEngine.GetService<GameStats>().Mental += -10;
            }
            if (p_key == Keys.X)
            {
                GameEngine.GetService<GameStats>().Mental += 10;
            }
            if (p_key == Keys.Q)
            {
                GameEngine.GetService<GameStats>().Insanity += -1;
            }
            if (p_key == Keys.W)
            {
                GameEngine.GetService<GameStats>().Insanity += 1;
            }

            #endregion

        }

        /// <summary>
        /// 	Called whenever a keyboard button is released
        /// </summary>
        /// <param name = "key">the key released</param>
        public void KeyReleased(Keys key)
        {
            if (key == (Keys)16)
            {
                m_shiftHeld = false;
            }
        }

        #endregion

        #region IAlarmListener implementation

        /// <summary>
        /// 	Called when an alarm event happens
        /// </summary>
        /// <param name = "message">the alarm message</param>
        public void OnAlarmEvent(string message)
        {
        }

        #endregion
    }
}
        #endregion